﻿using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;


enum State
{
    Menu,
    Game
}

enum MenuState
{
    Main,
    Upgrade,
    EndLevel
}

public class GameManager : MonoBehaviour
{
    //Levels
    public Player player;
    public LayerMask LevelLayer;

    public LevelMaster levelMaster;
    public UpgradeManager upgradeManager;

    private State currentState;

    //Main menu variables
    private MenuState currentMenuState;
    private Rect inGameMenuRect;
    private Rect upgradeButtonRect;
    private bool inGameMenu = false;
    private bool confirm = false;
    private GameObject lastHitLevel;

    //Stat screen variables
    private float enemyRatio;
    private float speedRatio;
    private float totalRatio;

    private float speedRatioBonus;
    private int enemyKilledNb;
    private int levelEnemyCount;
    private int experience;
    private bool win;
    private int levelReward;

    private delegate bool altGUIMethods();
    private altGUIMethods printUpgradeGUI;
    private altGUIMethods printEndLevelGUI;

	// Use this for initialization
	void Start () {
        currentState = State.Menu;
        currentMenuState = MenuState.Main;

        inGameMenuRect = new Rect(120, 50, 50, 50);
        upgradeButtonRect = new Rect(50, 50, 75, 50);

        EventManager<EndLevelStat>.AddListener("end level", onLevelEnd);
        EventManager.AddListener("start level", onStartLevel);

        printUpgradeGUI = upgradeManager.printUpgradeGUI;
	}
	
	// Update is called once per frame
	void Update () {
	    switch(currentState)
        {
            case State.Menu:
                switch (currentMenuState)
                {
                    case MenuState.Main:
                        Ray rayPlacement = Camera.main.ScreenPointToRay(Input.mousePosition);
                        RaycastHit hitPlacement;
                        //Cast the ray and check if it collide with something in the placementPlace's layer
                        //The cast is made on hover for placement indication on the grid
                        if (Physics.Raycast(rayPlacement, out hitPlacement, 3000, LevelLayer))
                        {
                            if(lastHitLevel && lastHitLevel != hitPlacement.collider.gameObject)
                            {
                                lastHitLevel.GetComponent<Level>().hoverOff();
                            }
                            if (hitPlacement.collider.gameObject.GetComponent<Level>().Available)
                            {
                                lastHitLevel = hitPlacement.collider.gameObject;
                                lastHitLevel.GetComponent<Level>().hoverOn();

                                if (Input.GetMouseButtonDown(0))
                                {
                                    setLevel(lastHitLevel.GetComponent<Level>());
                                }
                            }
                        }
                        else
                        {
                            if (lastHitLevel)
                            {
                                lastHitLevel.GetComponent<Level>().hoverOff();
                                lastHitLevel = null;
                            }
                        }
                        break;
                    case MenuState.Upgrade:

                        break;

                    case MenuState.EndLevel:
                        break;
                }

                break;

            case State.Game:
                
                break;
        }
	}

    void OnGUI()
    {
        switch (currentState)
        {
            case State.Menu:
                switch (currentMenuState)
                {
                    case MenuState.Main:
                        if (GUI.Button(upgradeButtonRect, "Upgrades"))
                        {
                            upgradeManager.ShowUpgrade = true;
                            currentMenuState = MenuState.Upgrade;
                        }
                        if (lastHitLevel)
                        {
                            Vector3 levelPos = Camera.main.WorldToScreenPoint(lastHitLevel.transform.position);
                            GUI.Label(new Rect(levelPos.x, Screen.height - levelPos.y - 60, 120, 50), "Level " + (lastHitLevel.GetComponent<Level>().Id + 1));
                        }
                        break;

                    case MenuState.Upgrade:

                        if (printUpgradeGUI != null)
                        {
                            if(!printUpgradeGUI())
                            {
                                currentMenuState = MenuState.Main;
                            }
                        }

                        break;

                    case MenuState.EndLevel:
                        if (printEndLevelGUI != null)
                        {
                            if (!printEndLevelGUI())
                            {
                                currentMenuState = MenuState.Main;
                            }
                        }
                        break;
                }
                break;

            case State.Game:
                if (inGameMenu)
                {
                    if (GUI.Button(new Rect(Screen.width / 2 - 50, Screen.height / 2, 100, 50), "Surrender"))
                    {
                        inGameMenu = false;
                        confirm = true;
                    }
                    if (GUI.Button(new Rect(Screen.width / 2 - 50, Screen.height / 2 + 75, 100, 50), "Return"))
                    {
                        Time.timeScale = 1;
                        inGameMenu = false;
                    } 
                }
                else
                {
                    if (!confirm)
                    {
                        if (GUI.Button(inGameMenuRect, "Menu"))
                        {
                            inGameMenu = true;
                            Time.timeScale = 0;
                        }     
                    }
                }
                if(confirm)
                {
                    if (GUI.Button(new Rect(Screen.width / 2 - 25, Screen.height / 2, 50, 50), "yes"))
                    {
                        Time.timeScale = 1;
                        levelMaster.surrender();
                        confirm = false;
                    }
                    if (GUI.Button(new Rect(Screen.width / 2 + 25, Screen.height / 2, 50, 50), "no"))
                    {
                        Time.timeScale = 1;
                        confirm = false;
                    }
                }
                break;
        }
    }

    private void setLevel(Level level)
    {
        EventManager<Level>.Raise("set level", level);
        level.hoverOff();
        currentState = State.Game;
    }

    public void onLevelEnd(EndLevelStat stat)
    {
        printEndLevelGUI = stat.printEndLevelGUI;
        currentState = State.Menu;
        currentMenuState = MenuState.EndLevel;

        //unlock next level
        stat.Level.UnlockOnWin.ForEach(l => l.Available = true);
    }

    public void onStartLevel()
    {
        player.gameObject.SetActive(true);
    }
}
